import React, { forwardRef, ReactNode, SVGAttributes } from 'react';
import { addUnit } from '../utils/format';
import { Dictionary } from '../utils/interface';
import { classnames, createBEM } from '../utils/namespace';
import { IconProps } from './interface';

export const NS = 'fnx-icon';
export const bem = createBEM(NS);

export const DEFAULT_SVG_PROPS: SVGAttributes<any> = {
	width: '1em',
	height: '1em',
	fill: 'currentColor',
	'aria-hidden': true,
	focusable: false,
};

export const DEFAULT_SVG_VIEW_BOX = '0 0 48 48';

export const DEFAULT_ICONS: Dictionary<ReactNode> = {
	'arrow-down': (
		<path d="M5.112 16.395l17.55 18.182a1.495 1.495 0 002.014.097l.107-.097 18.1-18.181a.4.4 0 00.117-.283v-3.126a.4.4 0 00-.683-.283L23.782 31.32 5.687 12.724a.4.4 0 00-.687.279v3.114a.4.4 0 00.112.278z"></path>
	),
	'arrow-left': (
		<path d="M31.705 5.112l-18.182 17.55a1.495 1.495 0 00-.097 2.014l.097.107 18.182 18.1a.4.4 0 00.282.117h3.127a.4.4 0 00.282-.683L16.78 23.782 35.376 5.687A.4.4 0 0035.098 5h-3.115a.4.4 0 00-.278.112z"></path>
	),
	'arrow-right': (
		<path d="M17.395 5.112l18.182 17.55c.553.55.586 1.424.097 2.014l-.097.107-18.181 18.1a.4.4 0 01-.283.117h-3.126a.4.4 0 01-.283-.683L32.32 23.782 13.724 5.687A.4.4 0 0114.003 5h3.114a.4.4 0 01.278.112z"></path>
	),
	'arrow-up': (
		<path d="M5.112 30.705l17.55-18.182a1.495 1.495 0 012.014-.097l.107.097 18.1 18.182a.4.4 0 01.117.282v3.127a.4.4 0 01-.683.282L23.782 15.78 5.687 34.376A.4.4 0 015 34.098v-3.115a.4.4 0 01.112-.278z"></path>
	),
	circle: (
		<path d="M 24 2 C 36.15 2 46 11.85 46 24 C 46 36.15 36.15 46 24 46 C 11.85 46 2 36.15 2 24 C 2 11.85 11.85 2 24 2 Z M 24 5 C 13.507 5 5 13.507 5 24 C 5 34.493 13.507 43 24 43 C 34.493 43 43 34.493 43 24 C 43 13.507 34.493 5 24 5 Z"></path>
	),
	cross: (
		<path d="M10.609 8.118L24.177 21.82 37.744 8.118a.4.4 0 01.285-.119h3.075a.4.4 0 01.284.681l-15.11 15.26 15.224 15.378a.4.4 0 01-.284.681h-3.075a.4.4 0 01-.284-.119L24.177 26.062 10.494 39.88a.4.4 0 01-.285.119H7.136a.4.4 0 01-.284-.681L22.076 23.94 6.966 8.68a.4.4 0 01.284-.682h3.074a.4.4 0 01.285.119z"></path>
	),
	fail: (
		<path d="M24.5 34a2.5 2.5 0 110 5 2.5 2.5 0 010-5zm1.1-26c.22 0 .4.18.4.4v22.2a.4.4 0 01-.4.4h-2.2a.4.4 0 01-.4-.4V8.4c0-.22.18-.4.4-.4h2.2z"></path>
	),
	minus: (
		<path d="M41.1 22.5c.22 0 .4.18.4.4v2.2a.4.4 0 01-.4.4H6.9a.4.4 0 01-.4-.4v-2.2c0-.22.18-.4.4-.4h34.2z"></path>
	),
	plus: (
		<path d="M25.1 6.5c.22 0 .4.18.4.4v15.6h15.6c.22 0 .4.18.4.4v2.2a.4.4 0 01-.4.4H25.5v15.6a.4.4 0 01-.4.4h-2.2a.4.4 0 01-.4-.4V25.5H6.9a.4.4 0 01-.4-.4v-2.2c0-.22.18-.4.4-.4h15.6V6.9c0-.22.18-.4.4-.4h2.2z"></path>
	),
	success: (
		<path d="M44.31 12.684L21.218 35.566a1.504 1.504 0 01-2.252-.157 1.468 1.468 0 01-.158-.136L3.69 20.292a.4.4 0 01.282-.684h3.09a.4.4 0 01.282.116l12.816 12.7 20.496-20.308a.4.4 0 01.282-.116h3.09a.4.4 0 01.282.684z"></path>
	),
	picture: (
		<>
			<path d="M38,4 C41.3137085,4 44,6.6862915 44,10 L44,38 C44,41.3137085 41.3137085,44 38,44 L10,44 C6.6862915,44 4,41.3137085 4,38 L4,10 C4,6.6862915 6.6862915,4 10,4 L38,4 Z M38,7 L10,7 C8.40231912,7 7.09633912,8.24891996 7.00509269,9.82372721 L7,10 L7,38 C7,39.5976809 8.24891996,40.9036609 9.82372721,40.9949073 L10,41 L38,41 C39.5976809,41 40.9036609,39.75108 40.9949073,38.1762728 L41,38 L41,37.332 L32.7808252,29.1126218 C32.0818755,28.4136721 30.9683937,28.3819016 30.2317592,29.0173105 L30.1291748,29.1126218 L17.242,41.9990101 L13,41.9990101 L28.6265729,26.372583 C30.18867,24.8104858 32.72133,24.8104858 34.2834271,26.372583 L40.3171606,32.4061764 C40.4733721,32.5623843 40.7266381,32.5623814 40.882846,32.4061699 C40.9578585,32.3311556 41,32.2294154 41,32.1233304 L41,10 C41,8.40231912 39.75108,7.09633912 38.1762728,7.00509269 L38,7 Z" />
			<path d="M16,12 C18.7614237,12 21,14.2385763 21,17 C21,19.7614237 18.7614237,22 16,22 C13.2385763,22 11,19.7614237 11,17 C11,14.2385763 13.2385763,12 16,12 Z M16,15 C14.8954305,15 14,15.8954305 14,17 C14,18.1045695 14.8954305,19 16,19 C17.1045695,19 18,18.1045695 18,17 C18,15.8954305 17.1045695,15 16,15 Z" />
		</>
	),
	'picture-wrong': (
		<path d="M26.6,41 C26.8209139,41 27,41.1790861 27,41.4 L27,43.6 C27,43.8209139 26.8209139,44 26.6,44 L10,44 C6.6862915,44 4,41.3137085 4,38 L4,10 C4,6.6862915 6.6862915,4 10,4 L38,4 C41.3137085,4 44,6.6862915 44,10 L44,27.593 C44,27.8139139 43.8209139,27.993 43.6,27.993 L41.4,27.993 C41.1790861,27.993 41,27.8139139 41,27.593 L41,10 C41,8.40231912 39.75108,7.09633912 38.1762728,7.00509269 L38,7 L10,7 C8.40231912,7 7.09633912,8.24891996 7.00509269,9.82372721 L7,10 L7,38 C7,39.5976809 8.24891996,40.9036609 9.82372721,40.9949073 L10,41 M40.6719687,31.2652801 L42.2275262,32.8204117 C42.383855,32.9765022 42.3838897,33.2297682 42.2277014,33.3859993 C42.2276688,33.3860319 42.2276362,33.3860645 42.2275059,33.3859993 L38.9039017,36.7082163 C38.7475587,36.8642927 38.7475058,37.1175587 38.903683,37.273801 C38.9037165,37.2738346 38.9037501,37.2738682 38.9038844,37.273801 L42.2275232,40.5964595 C42.3838364,40.7525657 42.3838737,41.0058317 42.2276871,41.1620645 C42.2276603,41.1620913 42.2276334,41.1621181 42.2275262,41.1620645 L40.6719687,42.717196 C40.5156899,42.8732755 40.2624843,42.8732759 40.1062051,42.7171968 L36.7818822,39.3938032 C36.6256468,39.2376241 36.3723857,39.2376567 36.2161905,39.3938759 L32.8937222,42.7171241 C32.7375275,42.8733444 32.4842657,42.8733766 32.3280313,42.717196 L30.7724738,41.1620645 C30.6161986,41.0059202 30.6161639,40.7526542 30.7723523,40.5964231 C30.772367,40.5964084 30.7723817,40.5963938 30.7724404,40.5964231 L34.0951519,37.2738374 C34.2513926,37.1176586 34.2513974,36.8643926 34.0951907,36.70818 C34.0951813,36.7081706 34.095172,36.7081613 34.0951346,36.70818 L30.7724577,33.3860357 C30.6161741,33.2298999 30.6161538,32.9766339 30.772351,32.8204117 C30.7723715,32.8203912 30.7723919,32.8203707 30.7724738,32.8204117 L32.3280313,31.2652801 C32.4843206,31.1092247 32.7375129,31.1092166 32.8938123,31.265262 L36.2171004,34.5872142 C36.3734109,34.7432343 36.6265891,34.7432343 36.7828996,34.5872142 L40.1061877,31.265262 C40.2624871,31.1092166 40.5156794,31.1092247 40.6719687,31.2652801 Z M13,40.9990101 L28.6265729,25.372583 C30.18867,23.8104858 32.72133,23.8104858 34.2834271,25.372583 L36.2211004,27.310141 C36.3773147,27.4663461 36.3773223,27.7196121 36.2211172,27.8758264 C36.1461012,27.9508469 36.0443547,27.992993 35.9382628,27.9929921 L32.6494405,27.9929653 C31.9483786,27.412271 30.9237784,27.4203861 30.2317592,28.0173105 L30.1291748,28.1126218 L17.3591558,40.8818615 C17.284142,40.9568707 17.1824041,40.9990101 17.0763217,40.9990101 L13,40.9990101 L13,40.9990101 Z M16,12 C18.7614237,12 21,14.2385763 21,17 C21,19.7614237 18.7614237,22 16,22 C13.2385763,22 11,19.7614237 11,17 C11,14.2385763 13.2385763,12 16,12 Z M16,15 C14.8954305,15 14,15.8954305 14,17 C14,18.1045695 14.8954305,19 16,19 C17.1045695,19 18,18.1045695 18,17 C18,15.8954305 17.1045695,15 16,15 Z" />
	),
	'cross-fill': (
		<path d="M24 2c12.15 0 22 9.85 22 22s-9.85 22-22 22S2 36.15 2 24 11.85 2 24 2zm-5.325 14h-3.111a.4.4 0 00-.283.683l7.018 7.018-7.616 7.616a.4.4 0 00.283.683h3.11a.4.4 0 00.282-.117l6.062-6.061 6.062 6.06a.4.4 0 00.283.118h3.111a.4.4 0 00.283-.683L26.542 23.7l7.017-7.017a.4.4 0 00-.283-.683h-3.112a.4.4 0 00-.283.117l-5.46 5.462-5.463-5.462a.4.4 0 00-.283-.117z"></path>
	),
	close: (
		<path d="M24 2c12.15 0 22 9.85 22 22s-9.85 22-22 22S2 36.15 2 24 11.85 2 24 2zm0 3C13.507 5 5 13.507 5 24s8.507 19 19 19 19-8.507 19-19S34.493 5 24 5zm-5.625 11.117L24 21.742l5.625-5.625a.4.4 0 01.283-.117h3.112a.4.4 0 01.283.683l-7.182 7.18 7.454 7.454a.4.4 0 01-.283.683H30.18a.4.4 0 01-.283-.117L24 25.985 18.1 31.883a.4.4 0 01-.283.117h-3.11a.4.4 0 01-.283-.683l7.453-7.453-7.181-7.181A.4.4 0 0114.98 16h3.112a.4.4 0 01.283.117z"></path>
	),
	file: (
		<path d="M38 4a6 6 0 016 6v28a6 6 0 01-6 6H10a6 6 0 01-6-6V10a6 6 0 016-6h28zm0 3H10a3 3 0 00-2.995 2.824L7 10v28a3 3 0 002.824 2.995L10 41h28a3 3 0 002.995-2.824L41 38V10a3 3 0 00-2.824-2.995L38 7zM23.6 29c.22 0 .4.18.4.4v2.2a.4.4 0 01-.4.4h-9.2a.4.4 0 01-.4-.4v-2.2c0-.22.18-.4.4-.4h9.2zm10-6c.22 0 .4.18.4.4v2.2a.4.4 0 01-.4.4H14.4a.4.4 0 01-.4-.4v-2.2c0-.22.18-.4.4-.4h19.2zm0-6c.22 0 .4.18.4.4v2.2a.4.4 0 01-.4.4H14.4a.4.4 0 01-.4-.4v-2.2c0-.22.18-.4.4-.4h19.2z"></path>
	),
	'star-full': (
		<path d="M25.846 4.449a4.259 4.259 0 011.894 1.97l3.92 8.265 8.768 1.325c2.28.345 3.86 2.547 3.528 4.918a4.402 4.402 0 01-1.216 2.483l-6.344 6.433 1.497 9.084c.39 2.362-1.135 4.605-3.405 5.01a4.03 4.03 0 01-2.646-.436L24 39.212l-7.842 4.289c-2.04 1.115-4.56.3-5.633-1.822a4.492 4.492 0 01-.419-2.752l1.498-9.084L5.26 23.41c-1.65-1.673-1.684-4.42-.076-6.135a4.117 4.117 0 012.387-1.266l8.768-1.325 3.92-8.264c1.02-2.15 3.521-3.031 5.587-1.971z" />
	),
};

const Icon = forwardRef<HTMLSpanElement, IconProps>((props, ref) => {
	const {
		className,
		name,
		component: SvgComponent,
		spin,
		children,
		viewBox,
		size,
		color,
		style,
		...rest
	} = props;

	let icon: ReactNode;

	if (SvgComponent) {
		icon = (
			<SvgComponent
				{...DEFAULT_SVG_PROPS}
				viewBox={viewBox || DEFAULT_SVG_VIEW_BOX}
			/>
		);
	} else if (children) {
		icon = (
			<svg
				{...DEFAULT_SVG_PROPS}
				viewBox={viewBox || DEFAULT_SVG_VIEW_BOX}
			>
				{children}
			</svg>
		);
	} else if (name) {
		const elements = DEFAULT_ICONS[name];

		if (elements) {
			icon = (
				<svg {...DEFAULT_SVG_PROPS} viewBox={DEFAULT_SVG_VIEW_BOX}>
					{elements}
				</svg>
			);
		}
	}

	return (
		<span
			className={classnames(bem({ spin }), className)}
			{...rest}
			style={{ color, fontSize: addUnit(size), ...style }}
			ref={ref}
		>
			{icon}
		</span>
	);
});

Icon.displayName = 'Icon';

export default Icon;
